﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;


namespace FFmpegVideoClip.Lib.Controls
{
    internal class RangeSelect :Control
    {
        public readonly record struct SelectRange(double SelectMin, double SelectMax);
        Track? track1, track2;
        Thumb? thumb1, thumb2;
        TextBlock? minText, maxText;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Track[] tracks = Tools.GetChilds<Track>(this).OrderBy(p => p.Name, StringComparer.OrdinalIgnoreCase).ToArray();
            track1 = tracks[0];
            thumb1 = track1.Thumb;
            track2 = tracks[1];
            thumb2 = track2.Thumb;

            thumb1.DragDelta += Thumb_DragDelta;
            thumb2.DragDelta += Thumb_DragDelta;

            IEnumerable<TextBlock> texts = Tools.GetChilds<TextBlock>(this);
            minText = texts.First(p => p.Name.Equals("Min", StringComparison.OrdinalIgnoreCase));
            maxText = texts.First(p => p.Name.Equals("Max", StringComparison.OrdinalIgnoreCase));
            SetText(GetSelectRange());
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            SelectRange range = GetSelectRange();
            SetText(range);
            drawingContext.DrawRectangle(Foreground, new Pen(Foreground, 0), GetRect(range));
        }

        private void SetText(SelectRange range)
        {
            if (minText != null)
                minText.Text = Tools.GetTimeSpanToString_Digit(TimeSpan.FromSeconds(range.SelectMin));
            if (maxText != null)
                maxText.Text = Tools.GetTimeSpanToString_Digit(TimeSpan.FromSeconds(range.SelectMax));
        }

        private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Thumb thumb = (Thumb)sender;
            double num;
            if (thumb == thumb1)
            {
                num = SelectValue1 + track1?.ValueFromDistance(e.HorizontalChange, e.VerticalChange) ?? 0;
                num = num < Minimum ? Minimum : num > Maximum ? Maximum : num;
                SelectValue1 = num;
            }
            else if (thumb == thumb2)
            {
                num = SelectValue2 + track2?.ValueFromDistance(e.HorizontalChange, e.VerticalChange) ?? 0;
                num = num < Minimum ? Minimum : num > Maximum ? Maximum : num;
                SelectValue2 = num;
            }
        }

        public double SelectValue1 { get => (double)GetValue(SelectValue1Property); set => SetValue(SelectValue1Property, value); }
        public static readonly DependencyProperty SelectValue1Property = DependencyProperty.Register(nameof(SelectValue1), typeof(double), typeof(RangeSelect), new PropertyMetadata(0d, (s, e) => ValueLimitAndUpdateUI(s, e)));

        

        public double SelectValue2 { get => (double)GetValue(SelectValue2Property); set => SetValue(SelectValue2Property, value); }
        public static readonly DependencyProperty SelectValue2Property = DependencyProperty.Register(nameof(SelectValue2), typeof(double), typeof(RangeSelect), new PropertyMetadata(0d, (s, e) => ValueLimitAndUpdateUI(s, e)));


        public double Minimum { get => (double)GetValue(MinimumProperty); set => SetValue(MinimumProperty, value); }
        public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(RangeSelect), new PropertyMetadata(0d, (s, e) => UpdateUI(s)));

        public double Maximum { get => (double)GetValue(MaximumProperty); set => SetValue(MaximumProperty, value); }
        public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(RangeSelect), new PropertyMetadata(0d, (s, e) => UpdateUI(s)));

        private static void UpdateUI(DependencyObject s)
        {
            RangeSelect rs = (RangeSelect)s;
            if (rs.Minimum > rs.Maximum)
            {
                rs.Maximum = rs.Minimum;
                return;
            }
            rs.Valuelimit();
            rs.InvalidateVisual();
        }
        private static void ValueLimitAndUpdateUI(DependencyObject s, DependencyPropertyChangedEventArgs e)
        {
            RangeSelect rs = (RangeSelect)s;
            double v = (double)e.NewValue;
            if (v < rs.Minimum)
            {
                rs.SelectValue1 = rs.Minimum;
                return;
            }
            else if (v > rs.Maximum)
            {
                rs.SelectValue1 = rs.Maximum;
                return; ;
            }
            else rs.InvalidateVisual();
        }
        private void Valuelimit()
        {
            if (SelectValue1 < Minimum)
                SelectValue1 = Minimum;
            if (SelectValue1 > Maximum)
                SelectValue1 = Maximum;
            if (SelectValue2 < Minimum)
                SelectValue2 = Minimum;
            if (SelectValue2 > Maximum)
                SelectValue2 = Maximum;
        }
        public SelectRange GetSelectRange()
        {
            if (SelectValue1 <= SelectValue2)
                return new SelectRange(SelectValue1, SelectValue2);
            else
                return new SelectRange(SelectValue2, SelectValue1);
        }
        private Rect GetRect(SelectRange selectRange)
        {
            double SecondsUIWidth = ActualWidth / (Maximum - Minimum);
            double UIPointXMin, UIPointXMax;
            UIPointXMin = (selectRange.SelectMin - Minimum) * SecondsUIWidth;
            UIPointXMax = (selectRange.SelectMax - Minimum) * SecondsUIWidth;
            return new Rect(new Point(UIPointXMin, 0), new Point(UIPointXMax, this.ActualHeight));
        }
    }
}
